
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_Hans">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>从模型创建表单 &#8212; Django 3.2.11.dev 文档</title>
    <link rel="stylesheet" href="../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../_static/language_data.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="表单资源（ Media 类）" href="media.html" />
    <link rel="prev" title="表单集" href="formsets.html" />



 
<script src="../../templatebuiltins.js"></script>
<script>
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../index.html">Django 3.2.11.dev 文档</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../index.html">Home</a>  |
        <a title="Table of contents" href="../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../genindex.html">Index</a>  |
        <a title="Module index" href="../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="formsets.html" title="表单集">previous</a>
     |
    <a href="../index.html" title="使用 Django" accesskey="U">up</a>
   |
    <a href="media.html" title="表单资源（ &lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;Media&lt;/span&gt;&lt;/code&gt; 类）">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="topics-forms-modelforms">
            
  <div class="section" id="s-creating-forms-from-models">
<span id="creating-forms-from-models"></span><h1>从模型创建表单<a class="headerlink" href="#creating-forms-from-models" title="永久链接至标题">¶</a></h1>
<div class="section" id="s-modelform">
<span id="modelform"></span><h2><code class="docutils literal notranslate"><span class="pre">ModelForm</span></code><a class="headerlink" href="#modelform" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.forms.ModelForm">
<em class="property">class </em><code class="descname">ModelForm</code><a class="headerlink" href="#django.forms.ModelForm" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>如果您正在构建一个数据库驱动的应用程序，那么您很有可能会用到与Django模型密切相关的表单。例如，您可能有一个 <code class="docutils literal notranslate"><span class="pre">BlogComment</span></code> 模型，并且您想创建一个让用户提交评论的表单。在这种情况下，在表单中定义字段类型是多余的，因为您已经在模型中定义了字段。</p>
<p>因此，Django 提供了一个辅助类让你可以从一个 Django 模型创建一个 <code class="docutils literal notranslate"><span class="pre">Form</span></code> 类。</p>
<p>例如:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Article</span>

<span class="go"># Create the form class.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">ArticleForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
<span class="gp">... </span>    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
<span class="gp">... </span>        <span class="n">model</span> <span class="o">=</span> <span class="n">Article</span>
<span class="gp">... </span>        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pub_date&#39;</span><span class="p">,</span> <span class="s1">&#39;headline&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">,</span> <span class="s1">&#39;reporter&#39;</span><span class="p">]</span>

<span class="go"># Creating a form to add an article.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">form</span> <span class="o">=</span> <span class="n">ArticleForm</span><span class="p">()</span>

<span class="go"># Creating a form to change an existing article.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">article</span> <span class="o">=</span> <span class="n">Article</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">form</span> <span class="o">=</span> <span class="n">ArticleForm</span><span class="p">(</span><span class="n">instance</span><span class="o">=</span><span class="n">article</span><span class="p">)</span>
</pre></div>
</div>
<div class="section" id="s-field-types">
<span id="field-types"></span><h3>字段类型<a class="headerlink" href="#field-types" title="永久链接至标题">¶</a></h3>
<p>生成的 <code class="docutils literal notranslate"><span class="pre">Form</span></code> 类将按照 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 属性中指定的顺序为每个指定的模型字段设置一个表单字段。</p>
<p>每个模型字段都有一个对应的默认表单字段。例如，模型中的 <code class="docutils literal notranslate"><span class="pre">CharField</span></code> 在表单中被表现为 <code class="docutils literal notranslate"><span class="pre">CharField</span></code> 。 <code class="docutils literal notranslate"><span class="pre">ManyToManyField</span></code> 则表现为 <code class="docutils literal notranslate"><span class="pre">MultipleChoiceField</span></code> 。以下是完整的转化清单：</p>
<table class="docutils">
<colgroup>
<col width="41%" />
<col width="59%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">模型字段</th>
<th class="head">表单字段</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.AutoField" title="django.db.models.AutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoField</span></code></a></td>
<td>不呈现在表单中</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.BigAutoField" title="django.db.models.BigAutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">BigAutoField</span></code></a></td>
<td>不呈现在表单中</td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.BigIntegerField" title="django.db.models.BigIntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">BigIntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a> 将 <code class="docutils literal notranslate"><span class="pre">min_value</span></code> 设置为-9223372036854775808，将 <code class="docutils literal notranslate"><span class="pre">max_value</span></code> 设置为9223372036854775807。</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.BinaryField" title="django.db.models.BinaryField"><code class="xref py py-class docutils literal notranslate"><span class="pre">BinaryField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.CharField" title="django.forms.CharField"><code class="xref py py-class docutils literal notranslate"><span class="pre">CharField</span></code></a> ，如果在模型字段上的 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.Field.editable" title="django.db.models.Field.editable"><code class="xref py py-attr docutils literal notranslate"><span class="pre">editable</span></code></a> 被设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> ，则不在表单中显示。</td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.BooleanField" title="django.db.models.BooleanField"><code class="xref py py-class docutils literal notranslate"><span class="pre">BooleanField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.BooleanField" title="django.forms.BooleanField"><code class="xref py py-class docutils literal notranslate"><span class="pre">BooleanField</span></code></a>, 或 <a class="reference internal" href="../../ref/forms/fields.html#django.forms.NullBooleanField" title="django.forms.NullBooleanField"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullBooleanField</span></code></a> （如果 <code class="docutils literal notranslate"><span class="pre">null=True</span></code> ）。</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.CharField" title="django.db.models.CharField"><code class="xref py py-class docutils literal notranslate"><span class="pre">CharField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.CharField" title="django.forms.CharField"><code class="xref py py-class docutils literal notranslate"><span class="pre">CharField</span></code></a> 将 <code class="docutils literal notranslate"><span class="pre">max_length</span></code> 设置为模型字段的 <code class="docutils literal notranslate"><span class="pre">max_length</span></code> ，如果模型中设置了 <code class="docutils literal notranslate"><span class="pre">null=True</span></code> ，会将 <a class="reference internal" href="../../ref/forms/fields.html#django.forms.CharField.empty_value" title="django.forms.CharField.empty_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">empty_value</span></code></a> 设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。</td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.DateField" title="django.db.models.DateField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.DateField" title="django.forms.DateField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.DateTimeField" title="django.db.models.DateTimeField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateTimeField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.DateTimeField" title="django.forms.DateTimeField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateTimeField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.DecimalField" title="django.db.models.DecimalField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DecimalField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.DecimalField" title="django.forms.DecimalField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DecimalField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.DurationField" title="django.db.models.DurationField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DurationField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.DurationField" title="django.forms.DurationField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DurationField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.EmailField" title="django.db.models.EmailField"><code class="xref py py-class docutils literal notranslate"><span class="pre">EmailField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.EmailField" title="django.forms.EmailField"><code class="xref py py-class docutils literal notranslate"><span class="pre">EmailField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.FileField" title="django.db.models.FileField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FileField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.FileField" title="django.forms.FileField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FileField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.FilePathField" title="django.db.models.FilePathField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FilePathField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.FilePathField" title="django.forms.FilePathField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FilePathField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.FloatField" title="django.db.models.FloatField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FloatField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.FloatField" title="django.forms.FloatField"><code class="xref py py-class docutils literal notranslate"><span class="pre">FloatField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.ForeignKey" title="django.db.models.ForeignKey"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForeignKey</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.ModelChoiceField" title="django.forms.ModelChoiceField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ModelChoiceField</span></code></a> （见下文）</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.ImageField" title="django.db.models.ImageField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ImageField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.ImageField" title="django.forms.ImageField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ImageField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.IntegerField" title="django.db.models.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">IPAddressField</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">IPAddressField</span></code></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.GenericIPAddressField" title="django.db.models.GenericIPAddressField"><code class="xref py py-class docutils literal notranslate"><span class="pre">GenericIPAddressField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.GenericIPAddressField" title="django.forms.GenericIPAddressField"><code class="xref py py-class docutils literal notranslate"><span class="pre">GenericIPAddressField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.JSONField" title="django.db.models.JSONField"><code class="xref py py-class docutils literal notranslate"><span class="pre">JSONField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.JSONField" title="django.forms.JSONField"><code class="xref py py-class docutils literal notranslate"><span class="pre">JSONField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.ManyToManyField" title="django.db.models.ManyToManyField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ManyToManyField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.ModelMultipleChoiceField" title="django.forms.ModelMultipleChoiceField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ModelMultipleChoiceField</span></code></a> （见下文）</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.NullBooleanField" title="django.db.models.NullBooleanField"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullBooleanField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.NullBooleanField" title="django.forms.NullBooleanField"><code class="xref py py-class docutils literal notranslate"><span class="pre">NullBooleanField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.PositiveBigIntegerField" title="django.db.models.PositiveBigIntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">PositiveBigIntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.PositiveIntegerField" title="django.db.models.PositiveIntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">PositiveIntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.PositiveSmallIntegerField" title="django.db.models.PositiveSmallIntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">PositiveSmallIntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.SlugField" title="django.db.models.SlugField"><code class="xref py py-class docutils literal notranslate"><span class="pre">SlugField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.SlugField" title="django.forms.SlugField"><code class="xref py py-class docutils literal notranslate"><span class="pre">SlugField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.SmallAutoField" title="django.db.models.SmallAutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">SmallAutoField</span></code></a></td>
<td>不呈现在表单中</td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.SmallIntegerField" title="django.db.models.SmallIntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">SmallIntegerField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.IntegerField" title="django.forms.IntegerField"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntegerField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.TextField" title="django.db.models.TextField"><code class="xref py py-class docutils literal notranslate"><span class="pre">TextField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.CharField" title="django.forms.CharField"><code class="xref py py-class docutils literal notranslate"><span class="pre">CharField</span></code></a> 设置中 <code class="docutils literal notranslate"><span class="pre">widget=forms.Textarea</span></code></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.TimeField" title="django.db.models.TimeField"><code class="xref py py-class docutils literal notranslate"><span class="pre">TimeField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.TimeField" title="django.forms.TimeField"><code class="xref py py-class docutils literal notranslate"><span class="pre">TimeField</span></code></a></td>
</tr>
<tr class="row-even"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.URLField" title="django.db.models.URLField"><code class="xref py py-class docutils literal notranslate"><span class="pre">URLField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.URLField" title="django.forms.URLField"><code class="xref py py-class docutils literal notranslate"><span class="pre">URLField</span></code></a></td>
</tr>
<tr class="row-odd"><td><a class="reference internal" href="../../ref/models/fields.html#django.db.models.UUIDField" title="django.db.models.UUIDField"><code class="xref py py-class docutils literal notranslate"><span class="pre">UUIDField</span></code></a></td>
<td><a class="reference internal" href="../../ref/forms/fields.html#django.forms.UUIDField" title="django.forms.UUIDField"><code class="xref py py-class docutils literal notranslate"><span class="pre">UUIDField</span></code></a></td>
</tr>
</tbody>
</table>
<p>如您所料， <code class="docutils literal notranslate"><span class="pre">ForeignKey</span></code> 和 <code class="docutils literal notranslate"><span class="pre">ManyToManyField</span></code> 模型字段类型是特殊情况：</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">ForeignKey</span></code> 由 <code class="docutils literal notranslate"><span class="pre">django.forms.ModelChoiceField</span></code> 表示， 它是一个 <code class="docutils literal notranslate"><span class="pre">ChoiceField</span></code> ，其选项是一个模型的 <code class="docutils literal notranslate"><span class="pre">QuerySet</span></code> 。</li>
<li><code class="docutils literal notranslate"><span class="pre">ManyToManyField</span></code> 由 <code class="docutils literal notranslate"><span class="pre">django.forms.ModelMultipleChoiceField</span></code> 表示，它是一个 <code class="docutils literal notranslate"><span class="pre">MultipleChoiceField</span></code> ，其选项为一个模型 <code class="docutils literal notranslate"><span class="pre">QuerySet</span></code> 。</li>
</ul>
<p>另外，每个生成的表单字段的属性设置如下：</p>
<ul class="simple">
<li>如果模型字段设置了 <code class="docutils literal notranslate"><span class="pre">blank=True</span></code> ，那么表单字段的 <code class="docutils literal notranslate"><span class="pre">required</span></code> 属性被设置为 <code class="docutils literal notranslate"><span class="pre">False</span></code> ，否则 <code class="docutils literal notranslate"><span class="pre">required=True</span></code> 。</li>
<li>表单字段的 <code class="docutils literal notranslate"><span class="pre">label</span></code> 设置为模型字段的 <code class="docutils literal notranslate"><span class="pre">verbose_name</span></code> ，并且首字母大写。</li>
<li>表单字段的 <code class="docutils literal notranslate"><span class="pre">help_text</span></code> 设置为模型字段的 <code class="docutils literal notranslate"><span class="pre">help_text</span></code> 。</li>
<li>如果模型字段设置了 <code class="docutils literal notranslate"><span class="pre">choices</span></code> ，那么表单字段的 <code class="docutils literal notranslate"><span class="pre">widget</span></code> 会被设置为 <code class="docutils literal notranslate"><span class="pre">Select</span></code> ，其选项来自模型字段的 <code class="docutils literal notranslate"><span class="pre">choices</span></code> 。这些选项通常包含一个默认选中的空选项。如果字段设置了必填，则会强制用户进行选择。如果模型字段设置了 <code class="docutils literal notranslate"><span class="pre">blank=False</span></code> 以及一个明确的 <code class="docutils literal notranslate"><span class="pre">default</span></code> 值，则表单字段中不会包含空选项（默认会选中 <code class="docutils literal notranslate"><span class="pre">default</span></code> 值）。</li>
</ul>
<p>最后，请注意，您可以覆盖给定模型字段对应的表单字段。参见下文  <a class="reference internal" href="#overriding-the-default-fields">覆盖默认字段</a> 。</p>
</div>
<div class="section" id="s-a-full-example">
<span id="a-full-example"></span><h3>一个完整的例子<a class="headerlink" href="#a-full-example" title="永久链接至标题">¶</a></h3>
<p>思考下下面这组模型：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>

<span class="n">TITLE_CHOICES</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="s1">&#39;MR&#39;</span><span class="p">,</span> <span class="s1">&#39;Mr.&#39;</span><span class="p">),</span>
    <span class="p">(</span><span class="s1">&#39;MRS&#39;</span><span class="p">,</span> <span class="s1">&#39;Mrs.&#39;</span><span class="p">),</span>
    <span class="p">(</span><span class="s1">&#39;MS&#39;</span><span class="p">,</span> <span class="s1">&#39;Ms.&#39;</span><span class="p">),</span>
<span class="p">]</span>

<span class="k">class</span> <span class="nc">Author</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="n">TITLE_CHOICES</span><span class="p">)</span>
    <span class="n">birth_date</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateField</span><span class="p">(</span><span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">null</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="n">authors</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ManyToManyField</span><span class="p">(</span><span class="n">Author</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;birth_date&#39;</span><span class="p">]</span>

<span class="k">class</span> <span class="nc">BookForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Book</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;authors&#39;</span><span class="p">]</span>
</pre></div>
</div>
<p>通过这些模型，上面的 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 子类将大致等同于（唯一的区别是 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法，这我们稍后会讨论）：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">forms</span>

<span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">forms</span><span class="o">.</span><span class="n">Form</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">forms</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">forms</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span>
        <span class="n">max_length</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span>
        <span class="n">widget</span><span class="o">=</span><span class="n">forms</span><span class="o">.</span><span class="n">Select</span><span class="p">(</span><span class="n">choices</span><span class="o">=</span><span class="n">TITLE_CHOICES</span><span class="p">),</span>
    <span class="p">)</span>
    <span class="n">birth_date</span> <span class="o">=</span> <span class="n">forms</span><span class="o">.</span><span class="n">DateField</span><span class="p">(</span><span class="n">required</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">BookForm</span><span class="p">(</span><span class="n">forms</span><span class="o">.</span><span class="n">Form</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">forms</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="n">authors</span> <span class="o">=</span> <span class="n">forms</span><span class="o">.</span><span class="n">ModelMultipleChoiceField</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="section" id="s-validation-on-a-modelform">
<span id="s-validation-on-modelform"></span><span id="validation-on-a-modelform"></span><span id="validation-on-modelform"></span><h3>验证 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code><a class="headerlink" href="#validation-on-a-modelform" title="永久链接至标题">¶</a></h3>
<p>验证 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 主要涉及两个步骤：</p>
<ol class="arabic simple">
<li><a class="reference internal" href="../../ref/forms/validation.html"><span class="doc">验证表单</span></a></li>
<li><a class="reference internal" href="../../ref/models/instances.html#validating-objects"><span class="std std-ref">验证模型实例</span></a></li>
</ol>
<p>和普通的表单验证一样，模型表单验证在调用 <a class="reference internal" href="../../ref/forms/api.html#django.forms.Form.is_valid" title="django.forms.Form.is_valid"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_valid()</span></code></a> 或访问 <a class="reference internal" href="../../ref/forms/api.html#django.forms.Form.errors" title="django.forms.Form.errors"><code class="xref py py-attr docutils literal notranslate"><span class="pre">errors</span></code></a> 属性时隐式触发，在调用 <code class="docutils literal notranslate"><span class="pre">full_clean()</span></code> 时显式触发，尽管在实际应用中你不大会用到后一种方法。</p>
<p><code class="docutils literal notranslate"><span class="pre">模型</span></code> 验证（ <a class="reference internal" href="../../ref/models/instances.html#django.db.models.Model.full_clean" title="django.db.models.Model.full_clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.full_clean()</span></code></a> ）在表单验证步骤中紧随表单的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法被调用后触发。</p>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">Clean 过程会以各种方式去修改传递给 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 构造方法的模型实例。例如，模型上的所有日期字段都将转换为实际的日期对象。验证失败可能会使底层模型实例处于不一致状态，因此不推荐对其重用。</p>
</div>
<div class="section" id="s-overriding-the-clean-method">
<span id="s-overriding-modelform-clean-method"></span><span id="overriding-the-clean-method"></span><span id="overriding-modelform-clean-method"></span><h4>覆盖clean()方法<a class="headerlink" href="#overriding-the-clean-method" title="永久链接至标题">¶</a></h4>
<p>您可以重写模型表单上的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法来提供额外的验证，方式和普通的表单一样。</p>
<p>访问模型对象对应的表单实例包含一个 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 属性，让它可以访问对应的模型实例。</p>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p><code class="docutils literal notranslate"><span class="pre">ModelForm.clean()</span></code> 方法设置了一个标识符，使程序在 <a class="reference internal" href="../../ref/models/instances.html#validating-objects"><span class="std std-ref">模型验证</span></a>  这步去验证标记为 <code class="docutils literal notranslate"><span class="pre">unique</span></code> 、 <code class="docutils literal notranslate"><span class="pre">unique_together</span></code> 或 <code class="docutils literal notranslate"><span class="pre">unique_for_date|month|year</span></code> 的模型字段的唯一性。</p>
<p class="last">如果您想覆盖 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法并保持当前的验证，您必须调用父类的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法。</p>
</div>
</div>
<div class="section" id="s-interaction-with-model-validation">
<span id="interaction-with-model-validation"></span><h4>与模型验证交互<a class="headerlink" href="#interaction-with-model-validation" title="永久链接至标题">¶</a></h4>
<p>作为验证过程的一部分， <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 将调用模型上与表单字段对应的每个字段的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法。如果您排除了一些模型字段，则验证将不会在这些字段上运行。更多有关字段clean及验证是如何工作的内容，请参阅 <a class="reference internal" href="../../ref/forms/validation.html"><span class="doc">表单验证</span></a> 文档。</p>
<p>模型的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法会在所有唯一性检查之前被调用。有关模型 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 钩子的更多信息，请参阅 <a class="reference internal" href="../../ref/models/instances.html#validating-objects"><span class="std std-ref">验证对象</span></a> 。</p>
</div>
<div class="section" id="s-considerations-regarding-model-s-error-messages">
<span id="s-considerations-regarding-model-errormessages"></span><span id="considerations-regarding-model-s-error-messages"></span><span id="considerations-regarding-model-errormessages"></span><h4>有关模型的 <code class="docutils literal notranslate"><span class="pre">error_messages</span></code> 的注意事项<a class="headerlink" href="#considerations-regarding-model-s-error-messages" title="永久链接至标题">¶</a></h4>
<p>在 <a class="reference internal" href="../../ref/forms/fields.html#django.forms.Field.error_messages" title="django.forms.Field.error_messages"><code class="xref py py-attr docutils literal notranslate"><span class="pre">表单字段</span></code></a> 级别或者 <a class="reference internal" href="#modelforms-overriding-default-fields"><span class="std std-ref">表单 Meta</span></a> 级别定义的错误信息优先级总是高于在 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.Field.error_messages" title="django.db.models.Field.error_messages"><code class="xref py py-attr docutils literal notranslate"><span class="pre">模型字段</span></code></a> 级别定义的。</p>
<p>在 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.Field.error_messages" title="django.db.models.Field.error_messages"><code class="xref py py-attr docutils literal notranslate"><span class="pre">模型字段</span></code></a> 上定义的错误信息只有在 <a class="reference internal" href="../../ref/models/instances.html#validating-objects"><span class="std std-ref">模型验证</span></a> 步骤引发 <code class="docutils literal notranslate"><span class="pre">ValidationError</span></code> 时才会使用，并且没有在表单级定义相应的错误信息。</p>
<p>您可以通过添加 <a class="reference internal" href="../../ref/exceptions.html#django.core.exceptions.NON_FIELD_ERRORS" title="django.core.exceptions.NON_FIELD_ERRORS"><code class="xref py py-data docutils literal notranslate"><span class="pre">NON_FIELD_ERRORS</span></code></a> 键到 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 内部的 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类的 <code class="docutils literal notranslate"><span class="pre">error_messages</span></code> 中来覆盖模型验证引发的 <code class="docutils literal notranslate"><span class="pre">NON_FIELD_ERRORS</span></code> 错误信息。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="kn">import</span> <span class="n">NON_FIELD_ERRORS</span>
<span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>

<span class="k">class</span> <span class="nc">ArticleForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">error_messages</span> <span class="o">=</span> <span class="p">{</span>
            <span class="n">NON_FIELD_ERRORS</span><span class="p">:</span> <span class="p">{</span>
                <span class="s1">&#39;unique_together&#39;</span><span class="p">:</span> <span class="s2">&quot;</span><span class="si">%(model_name)s</span><span class="s2">&#39;s </span><span class="si">%(field_labels)s</span><span class="s2"> are not unique.&quot;</span><span class="p">,</span>
            <span class="p">}</span>
        <span class="p">}</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-the-save-method">
<span id="s-topics-modelform-save"></span><span id="the-save-method"></span><span id="topics-modelform-save"></span><h3><code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法<a class="headerlink" href="#the-save-method" title="永久链接至标题">¶</a></h3>
<p>每个 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 也有 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法。此方法根据绑定到表单的数据创建并保存数据库对象。 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 的子类可接受一个现有的模型实例作为关键字参数 <code class="docutils literal notranslate"><span class="pre">instance</span></code> ；如果提供了，则 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 会更新这个实例。如果没有，则 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 会创建一个对应模型的新实例。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Article</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.forms</span> <span class="kn">import</span> <span class="n">ArticleForm</span>

<span class="go"># Create a form instance from POST data.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">ArticleForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">)</span>

<span class="go"># Save a new Article object from the form&#39;s data.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">new_article</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>

<span class="go"># Create a form to edit an existing Article, but use</span>
<span class="go"># POST data to populate the form.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">Article</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">ArticleForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="n">a</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>请注意，如果表单 <a class="reference internal" href="#validation-on-modelform"><span class="std std-ref">尚未验证</span></a> ，调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 将通过检查 <code class="docutils literal notranslate"><span class="pre">form.errors</span></code> 来实现验证。如果表单验证不过，则会引发 <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> —— 比如，如果 <code class="docutils literal notranslate"><span class="pre">form.errors</span></code> 返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
<p>如果一个可选字段没有出现在表单的数据中，并且您给这个模型字段设置了 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.Field.default" title="django.db.models.Field.default"><code class="xref py py-attr docutils literal notranslate"><span class="pre">default</span></code></a> ，那么对应的模型实例会使用这个值作为结果。此行为不适用于使用以下组件的字段： <a class="reference internal" href="../../ref/forms/widgets.html#django.forms.CheckboxInput" title="django.forms.CheckboxInput"><code class="xref py py-class docutils literal notranslate"><span class="pre">CheckboxInput</span></code></a> 、 <a class="reference internal" href="../../ref/forms/widgets.html#django.forms.CheckboxSelectMultiple" title="django.forms.CheckboxSelectMultiple"><code class="xref py py-class docutils literal notranslate"><span class="pre">CheckboxSelectMultiple</span></code></a> 或者 <a class="reference internal" href="../../ref/forms/widgets.html#django.forms.SelectMultiple" title="django.forms.SelectMultiple"><code class="xref py py-class docutils literal notranslate"><span class="pre">SelectMultiple</span></code></a> （或者所有其 <a class="reference internal" href="../../ref/forms/widgets.html#django.forms.Widget.value_omitted_from_data" title="django.forms.Widget.value_omitted_from_data"><code class="xref py py-meth docutils literal notranslate"><span class="pre">value_omitted_from_data()</span></code></a> 方法总是返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 的组件），因为未勾选的复选框和未选中的 <code class="docutils literal notranslate"><span class="pre">&lt;select</span> <span class="pre">multiple&gt;</span></code> 不会出现在HTML表单提交的数据中。如果您正在设计API并且希望使用这些组件之一的字段有默认回退行为，请使用自定义表单字段或组件。</p>
<p><code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法接受一个可选参数 <code class="docutils literal notranslate"><span class="pre">commit</span></code> ，它的值是 <code class="docutils literal notranslate"><span class="pre">True</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。如果调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 的时候使用 <code class="docutils literal notranslate"><span class="pre">commit=False</span></code> ，那么它会返回一个尚未保存到数据库的对象。在这种情况下，需要您自己在生成的模型实例上调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 。如果要在保存对象之前对对象执行自定义操作，或者要使用其中一个专用的 <a class="reference internal" href="../../ref/models/instances.html#ref-models-force-insert"><span class="std std-ref">模型保存选项</span></a> ，这很有用。 <code class="docutils literal notranslate"><span class="pre">commit</span></code> 的值默认为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
<p>另一个使用 <code class="docutils literal notranslate"><span class="pre">commit=False</span></code> 的作用，您可以在模型与另一个模型有多对多关系的时候看到。如果您的模型具有多对多关系，并且在保存表单时指定了 <code class="docutils literal notranslate"><span class="pre">commit=False</span></code> ，Django无法立即保存多对多关系的表单数据。这是因为实例的多对多数据只有实例在数据库中存在时才能保存。</p>
<p>要解决这个问题，Django会在每次使用 <code class="docutils literal notranslate"><span class="pre">commit=False</span></code> 保存表单时，向 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 子类添加一个 <code class="docutils literal notranslate"><span class="pre">save_m2m()</span></code> 方法。在您手动保存表单生成的实例后，可以调用 <code class="docutils literal notranslate"><span class="pre">save_m2m()</span></code> 来保存多对多的表单数据。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Create a form instance with POST data.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">f</span> <span class="o">=</span> <span class="n">AuthorForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">)</span>

<span class="c1"># Create, but don&#39;t save the new author instance.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">new_author</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

<span class="c1"># Modify the author in some way.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">new_author</span><span class="o">.</span><span class="n">some_field</span> <span class="o">=</span> <span class="s1">&#39;some_value&#39;</span>

<span class="c1"># Save the new instance.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">new_author</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>

<span class="c1"># Now, save the many-to-many data for the form.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">f</span><span class="o">.</span><span class="n">save_m2m</span><span class="p">()</span>
</pre></div>
</div>
<p>只有在您使用 <code class="docutils literal notranslate"><span class="pre">save(commit=False)</span></code> 的时候才需要调用 <code class="docutils literal notranslate"><span class="pre">save_m2m()</span></code> 。当您在表单上使用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 时，无需调用其他方法，所有数据（包括多对多数据）都会被保存。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Create a form instance with POST data.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">Author</span><span class="p">()</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">f</span> <span class="o">=</span> <span class="n">AuthorForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="n">a</span><span class="p">)</span>

<span class="c1"># Create and save the new author instance. There&#39;s no need to do anything else.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">new_author</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>除了  <code class="docutils literal notranslate"><span class="pre">save()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">save_m2m()</span></code> 方法之外，<code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 与普通的表单工作方式一样。例如，用 <code class="docutils literal notranslate"><span class="pre">is_valid()</span></code> 方法来检查合法性，用 <code class="docutils literal notranslate"><span class="pre">is_multipart()</span></code> 方法来确定表单是否需要multipart文件上传（之后是否必须将 <code class="docutils literal notranslate"><span class="pre">request.FILES</span></code> 传递给表单），等等。更多相关信息，请参阅 <a class="reference internal" href="../../ref/forms/api.html#binding-uploaded-files"><span class="std std-ref">将上传的文件绑定到表单中</span></a> 。</p>
</div>
<div class="section" id="s-selecting-the-fields-to-use">
<span id="s-modelforms-selecting-fields"></span><span id="selecting-the-fields-to-use"></span><span id="modelforms-selecting-fields"></span><h3>选择要使用的字段<a class="headerlink" href="#selecting-the-fields-to-use" title="永久链接至标题">¶</a></h3>
<p>强烈建议您使用 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 属性来显式设置所有应在表单中编辑的字段。如果不这样做，当一张表单不慎允许用户设置某些字段，尤其是在将新字段添加到模型中时，很容易导致安全问题。根据表单渲染方式的不同，甚至可能不会在网页上显示问题。</p>
<p>The alternative approach would be to include all fields automatically, or
remove only some. This fundamental approach is known to be much less secure
and has led to serious exploits on major websites (e.g. <a class="reference external" href="https://github.blog/2012-03-04-public-key-security-vulnerability-and-mitigation/">GitHub</a>).</p>
<p>但是，有两种简单的方法保证你不会出现这些安全问题：</p>
<ol class="arabic">
<li><p class="first">将 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 属性设置为特殊值 <code class="docutils literal notranslate"><span class="pre">'__all__'</span></code> 以表明需要使用模型中的所有字段。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>

<span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="s1">&#39;__all__&#39;</span>
</pre></div>
</div>
</li>
<li><p class="first">将 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 中Meta类的 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 属性设置为表单中需要排除的字段列表。</p>
<p>例如:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">PartialAuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">exclude</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;title&#39;</span><span class="p">]</span>
</pre></div>
</div>
<p>由于 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 模型有三个字段 <code class="docutils literal notranslate"><span class="pre">name</span></code>、 <code class="docutils literal notranslate"><span class="pre">title</span></code> 和 <code class="docutils literal notranslate"><span class="pre">birth_date</span></code> ，上例的结果是字段 <code class="docutils literal notranslate"><span class="pre">name</span></code> 和 <code class="docutils literal notranslate"><span class="pre">birth_date</span></code> 会呈现在表单中。</p>
</li>
</ol>
<p>不管使用哪一种，字段会按模型中定义的顺序在表单中出现， <code class="docutils literal notranslate"><span class="pre">ManyToManyField</span></code>&nbsp;会排在最后。</p>
<p>另外，Django有个规则：如果您在模型字段中定义了 <code class="docutils literal notranslate"><span class="pre">editable=False</span></code> ， <a href="#id1"><span class="problematic" id="id2">*</span></a>任何*使用 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code>&nbsp;给该模型创建的表单都不会包含这个字段。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>任何没在上面逻辑中包含的表单字段都会不被表单的 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法处理。另外，如果手动将排除的字段添加回表单，它们也不会被模型实例初始化。</p>
<p>Django会阻止任何尝试保存不完整模型的行为，所以如果模型不允许缺省的字段为空，并且没有为该字段提供缺省值，那么任何尝试用这种字段的 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 的 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法都会失败。为了避免这种情况，您必须使用初始值实例化您模型中缺省但又必填的字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">author</span> <span class="o">=</span> <span class="n">Author</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s1">&#39;Mr&#39;</span><span class="p">)</span>
<span class="n">form</span> <span class="o">=</span> <span class="n">PartialAuthorForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="n">author</span><span class="p">)</span>
<span class="n">form</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>或者，您可以使用 <code class="docutils literal notranslate"><span class="pre">save(commit=False)</span></code> 然后手动设置其他必填字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">form</span> <span class="o">=</span> <span class="n">PartialAuthorForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">)</span>
<span class="n">author</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="n">author</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s1">&#39;Mr&#39;</span>
<span class="n">author</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p class="last">更多关于使用 <code class="docutils literal notranslate"><span class="pre">save(commit=False)</span></code> 的详细内容，请参阅 <a class="reference internal" href="#the-save-method">保存表单章节</a> 。</p>
</div>
</div>
<div class="section" id="s-overriding-the-default-fields">
<span id="s-modelforms-overriding-default-fields"></span><span id="overriding-the-default-fields"></span><span id="modelforms-overriding-default-fields"></span><h3>覆盖默认字段<a class="headerlink" href="#overriding-the-default-fields" title="永久链接至标题">¶</a></h3>
<p>之前在 <a class="reference internal" href="#field-types">字段类型</a> 表格中介绍的默认字段类型都是相对合适的。如果您的模型中有一个 <code class="docutils literal notranslate"><span class="pre">DateField</span></code> ，您可能希望在表单中将它展示为 <code class="docutils literal notranslate"><span class="pre">DateField</span></code> 。但 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 可以让您灵活地改变给定模型的表单字段。</p>
<p>要为字段指定自定义组件，请使用内部 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类的 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 属性。它应该是一个映射字段名到组建类或组件实例的字典。</p>
<p>例如，如果您希望 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 的 <code class="docutils literal notranslate"><span class="pre">name</span></code> 属性的 <code class="docutils literal notranslate"><span class="pre">CharField</span></code> 由 <code class="docutils literal notranslate"><span class="pre">&lt;textarea&gt;</span></code> 代替默认的 <code class="docutils literal notranslate"><span class="pre">&lt;input</span> <span class="pre">type=&quot;text&quot;&gt;</span></code> 来表示，您可以重写字段的部件：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span><span class="p">,</span> <span class="n">Textarea</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>

<span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;birth_date&#39;</span><span class="p">)</span>
        <span class="n">widgets</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">Textarea</span><span class="p">(</span><span class="n">attrs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;cols&#39;</span><span class="p">:</span> <span class="mi">80</span><span class="p">,</span> <span class="s1">&#39;rows&#39;</span><span class="p">:</span> <span class="mi">20</span><span class="p">}),</span>
        <span class="p">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">widgets</span></code> 字典接受任何 widget 实例（例如 <code class="docutils literal notranslate"><span class="pre">Textarea(...)</span></code> ）或类（例如 <code class="docutils literal notranslate"><span class="pre">Textarea</span></code>）。注意，对于具有非空 <code class="docutils literal notranslate"><span class="pre">choices</span></code> 属性的模型字段，<code class="docutils literal notranslate"><span class="pre">widgets</span></code> 字典会被忽略。在这个例子里，你必须覆盖表单字段来使用不同的 widget 。</p>
<p>同样的，如果您想进一步自定义一个字段，还可以指定内部Meta类的 <code class="docutils literal notranslate"><span class="pre">labels</span></code> 、 <code class="docutils literal notranslate"><span class="pre">help_texts</span></code> 和 <code class="docutils literal notranslate"><span class="pre">error_messages</span></code> 属性。</p>
<p>例如您想自定义 <code class="docutils literal notranslate"><span class="pre">name</span></code> 字段中所有面向用户的字符文本：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;birth_date&#39;</span><span class="p">)</span>
        <span class="n">labels</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;Writer&#39;</span><span class="p">),</span>
        <span class="p">}</span>
        <span class="n">help_texts</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;Some useful help text.&#39;</span><span class="p">),</span>
        <span class="p">}</span>
        <span class="n">error_messages</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="p">{</span>
                <span class="s1">&#39;max_length&#39;</span><span class="p">:</span> <span class="n">_</span><span class="p">(</span><span class="s2">&quot;This writer&#39;s name is too long.&quot;</span><span class="p">),</span>
            <span class="p">},</span>
        <span class="p">}</span>
</pre></div>
</div>
<p>您还可以指定  <code class="docutils literal notranslate"><span class="pre">field_classes</span></code> 来自定义表单实例化的字段类型：</p>
<p>例如，如果您想对 <code class="docutils literal notranslate"><span class="pre">slug</span></code> 字段使用 <code class="docutils literal notranslate"><span class="pre">MySlugFormField</span></code> ，您可以这样做：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Article</span>

<span class="k">class</span> <span class="nc">ArticleForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Article</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pub_date&#39;</span><span class="p">,</span> <span class="s1">&#39;headline&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">,</span> <span class="s1">&#39;reporter&#39;</span><span class="p">,</span> <span class="s1">&#39;slug&#39;</span><span class="p">]</span>
        <span class="n">field_classes</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;slug&#39;</span><span class="p">:</span> <span class="n">MySlugFormField</span><span class="p">,</span>
        <span class="p">}</span>
</pre></div>
</div>
<p>最后，如果您想完全控制一个字段（包括它的类型，验证，必填等等），您可以通过声明指定字段来做到这一点，就像在一个普通的 <code class="docutils literal notranslate"><span class="pre">Form</span></code> 中那样声明。</p>
<p>如果您想指定一个字段的验证器，可以通过声明定义该字段并设置其 <code class="docutils literal notranslate"><span class="pre">validators</span></code> 参数来实现：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">CharField</span><span class="p">,</span> <span class="n">ModelForm</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Article</span>

<span class="k">class</span> <span class="nc">ArticleForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="n">slug</span> <span class="o">=</span> <span class="n">CharField</span><span class="p">(</span><span class="n">validators</span><span class="o">=</span><span class="p">[</span><span class="n">validate_slug</span><span class="p">])</span>

    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Article</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pub_date&#39;</span><span class="p">,</span> <span class="s1">&#39;headline&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">,</span> <span class="s1">&#39;reporter&#39;</span><span class="p">,</span> <span class="s1">&#39;slug&#39;</span><span class="p">]</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>当您像这样显式地实例化了一个表单字段，理解 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 和普通  <code class="docutils literal notranslate"><span class="pre">Form</span></code> 的关系很重要。</p>
<p><code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 是一个可以自动生成特定字段的 <code class="docutils literal notranslate"><span class="pre">Form</span></code> 。哪些字段可以自动生成取决于 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类的内容，以及是否已经被明确定义过。总的来说 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code>  <strong>仅会</strong> 自动生成表单中 <strong>缺失</strong> 的字段，或者说，没被明确定义的字段。</p>
<p>声明定义的字段会保持原样，因此，任何对 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 属性（例如 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 、 <code class="docutils literal notranslate"><span class="pre">labels</span></code> 、 <code class="docutils literal notranslate"><span class="pre">help_texts</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">error_messages</span></code>）的自定义设置都会被忽略；它们仅适用于自动生成的字段。</p>
<p>同样，显式定义的字段不会从对应的模型中获取他们的属性（比如 <code class="docutils literal notranslate"><span class="pre">max_length</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">required</span></code>）。如果要保持模型中指定的行为，则必须在声明表单字段时显式设置相关参数。</p>
<p>例如，假设 <code class="docutils literal notranslate"><span class="pre">Article</span></code> 模型像下面这样：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Article</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">headline</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span>
        <span class="n">max_length</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
        <span class="n">null</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">help_text</span><span class="o">=</span><span class="s1">&#39;Use puns liberally&#39;</span><span class="p">,</span>
    <span class="p">)</span>
    <span class="n">content</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">TextField</span><span class="p">()</span>
</pre></div>
</div>
<p>且您希望对 <code class="docutils literal notranslate"><span class="pre">headline</span></code> 进行自定义验证，在保留指定的 <code class="docutils literal notranslate"><span class="pre">blank</span></code> 和 <code class="docutils literal notranslate"><span class="pre">help_text</span></code> 值同时，您可以像这样定义 <code class="docutils literal notranslate"><span class="pre">ArticleForm</span></code> ：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ArticleForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="n">headline</span> <span class="o">=</span> <span class="n">MyFormField</span><span class="p">(</span>
        <span class="n">max_length</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
        <span class="n">required</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">help_text</span><span class="o">=</span><span class="s1">&#39;Use puns liberally&#39;</span><span class="p">,</span>
    <span class="p">)</span>

    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Article</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;headline&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">]</span>
</pre></div>
</div>
<p>您必须确保表单字段的类型可用于设置对应模型字段的内容。如果它们不兼容，您会因为没有发生隐式转换而得到一个 <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> 。</p>
<p class="last">更多有关字段及其参数的内容，请参阅 <a class="reference internal" href="../../ref/forms/fields.html"><span class="doc">表单字段文档</span></a> 。</p>
</div>
</div>
<div class="section" id="s-enabling-localization-of-fields">
<span id="enabling-localization-of-fields"></span><h3>启用对字段的本地化<a class="headerlink" href="#enabling-localization-of-fields" title="永久链接至标题">¶</a></h3>
<p>默认情况下， <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 中的字段不会本地化他们的数据。要为字段启用本地化，您可以在 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类中使用 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 属性。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">ModelForm</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">ModelForm</span><span class="p">):</span>
<span class="gp">... </span>    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
<span class="gp">... </span>        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
<span class="gp">... </span>        <span class="n">localized_fields</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;birth_date&#39;</span><span class="p">,)</span>
</pre></div>
</div>
<p>如果 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 设置为特殊值 <code class="docutils literal notranslate"><span class="pre">'__all__'</span></code> ，则所有字段都将被本地化。</p>
</div>
<div class="section" id="s-form-inheritance">
<span id="form-inheritance"></span><h3>表单继承<a class="headerlink" href="#form-inheritance" title="永久链接至标题">¶</a></h3>
<p>与普通表单一样，您可以通过继承它们来扩展和重用 <code class="docutils literal notranslate"><span class="pre">ModelForms</span></code> 。如果您需要在父类中声明额外字段或额外方法以用于从模型派生的多个表单中，则此方法非常有用。例如，使用之前的 <code class="docutils literal notranslate"><span class="pre">ArticleForm</span></code> 类。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">EnhancedArticleForm</span><span class="p">(</span><span class="n">ArticleForm</span><span class="p">):</span>
<span class="gp">... </span>    <span class="k">def</span> <span class="nf">clean_pub_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span>        <span class="o">...</span>
</pre></div>
</div>
<p>这会创建一个与 <code class="docutils literal notranslate"><span class="pre">ArticleForm</span></code> 行为相同的表单，除了 <code class="docutils literal notranslate"><span class="pre">pub_date</span></code> 字段会有一些额外的验证和cleaning。</p>
<p>如果要更改 <code class="docutils literal notranslate"><span class="pre">Meta.fields</span></code> 或 <code class="docutils literal notranslate"><span class="pre">Meta.exclude</span></code> 列表，您也可以继承父类的内部 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">RestrictedArticleForm</span><span class="p">(</span><span class="n">EnhancedArticleForm</span><span class="p">):</span>
<span class="gp">... </span>    <span class="k">class</span> <span class="nc">Meta</span><span class="p">(</span><span class="n">ArticleForm</span><span class="o">.</span><span class="n">Meta</span><span class="p">):</span>
<span class="gp">... </span>        <span class="n">exclude</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;body&#39;</span><span class="p">,)</span>
</pre></div>
</div>
<p>这相比 <code class="docutils literal notranslate"><span class="pre">EnhancedArticleForm</span></code> 增加了额外方法，并修改了原始的 <code class="docutils literal notranslate"><span class="pre">ArticleForm.Meta</span></code> 以删除一个字段。</p>
<p>然而，有几项需要注意。</p>
<ul>
<li><p class="first">适用于普通的Python名称解析规则。如果您有多个声明 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 内部类的基类，就是说如果声明了子类的 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 就会使用它，否则就用第一个父类的 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 。</p>
</li>
<li><p class="first">可以同时继承 <code class="docutils literal notranslate"><span class="pre">Form</span></code> 和 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> ，但是，您必须确保 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 在MRO中出现在首位。这是因为这些类依赖于不同的元类，而一个类只能有一个元类。</p>
</li>
<li><p class="first">通过在子类上将名称设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> ，可以声明性地移除从父类继承的 <code class="docutils literal notranslate"><span class="pre">Field</span></code> 。</p>
<p>您只能使用这种技术排除父类中声明定义的字段；它不会阻止 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 元类生成默认字段。要排除默认字段，请参阅 <a class="reference internal" href="#modelforms-selecting-fields"><span class="std std-ref">选择要使用的字段</span></a> 。</p>
</li>
</ul>
</div>
<div class="section" id="s-providing-initial-values">
<span id="providing-initial-values"></span><h3>提供初始值<a class="headerlink" href="#providing-initial-values" title="永久链接至标题">¶</a></h3>
<p>与普通表单一样，可以在实例化表单时通过指定 <code class="docutils literal notranslate"><span class="pre">initial</span></code> 参数来指定表单的初始值。以这种方式提供的初始值会覆盖表单字段的初始值以及对应模型实例的初始值。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">article</span> <span class="o">=</span> <span class="n">Article</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">article</span><span class="o">.</span><span class="n">headline</span>
<span class="go">&#39;My headline&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">form</span> <span class="o">=</span> <span class="n">ArticleForm</span><span class="p">(</span><span class="n">initial</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;headline&#39;</span><span class="p">:</span> <span class="s1">&#39;Initial headline&#39;</span><span class="p">},</span> <span class="n">instance</span><span class="o">=</span><span class="n">article</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;headline&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="p">()</span>
<span class="go">&#39;Initial headline&#39;</span>
</pre></div>
</div>
</div>
<div class="section" id="s-modelform-factory-function">
<span id="s-modelforms-factory"></span><span id="modelform-factory-function"></span><span id="modelforms-factory"></span><h3>ModelForm的工厂函数<a class="headerlink" href="#modelform-factory-function" title="永久链接至标题">¶</a></h3>
<p>您可以不使用类定义，而是使用独立函数 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelform_factory" title="django.forms.models.modelform_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelform_factory()</span></code></a> 来创建给定模型的表单。如果您没有很多自定义设置，这可能会更方便：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">modelform_factory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Book</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">BookForm</span> <span class="o">=</span> <span class="n">modelform_factory</span><span class="p">(</span><span class="n">Book</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;author&quot;</span><span class="p">,</span> <span class="s2">&quot;title&quot;</span><span class="p">))</span>
</pre></div>
</div>
<p>这也可以用来对已有表单进行修改，例如给字段指定使用组件：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">Textarea</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Form</span> <span class="o">=</span> <span class="n">modelform_factory</span><span class="p">(</span><span class="n">Book</span><span class="p">,</span> <span class="n">form</span><span class="o">=</span><span class="n">BookForm</span><span class="p">,</span>
<span class="gp">... </span>                         <span class="n">widgets</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;title&quot;</span><span class="p">:</span> <span class="n">Textarea</span><span class="p">()})</span>
</pre></div>
</div>
<p>要包含的字段可以使用 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 和 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 关键字参数或 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 内部的 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类中相应的属性来指定。请参阅 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> <a class="reference internal" href="#modelforms-selecting-fields"><span class="std std-ref">选择要使用的字段</span></a> 文档。</p>
<p>... 或者为个别字段启用本地化功能：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Form</span> <span class="o">=</span> <span class="n">modelform_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">form</span><span class="o">=</span><span class="n">AuthorForm</span><span class="p">,</span> <span class="n">localized_fields</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;birth_date&quot;</span><span class="p">,))</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-model-formsets">
<span id="s-id1"></span><span id="model-formsets"></span><span id="id1"></span><h2>模型表单集<a class="headerlink" href="#model-formsets" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.forms.models.BaseModelFormSet">
<em class="property">class </em><code class="descclassname">models.</code><code class="descname">BaseModelFormSet</code><a class="headerlink" href="#django.forms.models.BaseModelFormSet" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>和 <a class="reference internal" href="formsets.html"><span class="doc">regular formsets</span></a> 一样，Django提供了几个增强的formset类，可以很方便地配合Django模型使用。让我们重用下上面的 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 模型：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">modelformset_factory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>使用 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 参数限制formset仅使用给定的字段。或者，您可以使用排除法，指定排除哪些字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;birth_date&#39;</span><span class="p">,))</span>
</pre></div>
</div>
<p>这将创建一个能够处理与 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 模型相关数据的formset。它运行起来就像一个普通的formset：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">formset</span><span class="p">)</span>
<span class="go">&lt;input type=&quot;hidden&quot; name=&quot;form-TOTAL_FORMS&quot; value=&quot;1&quot; id=&quot;id_form-TOTAL_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-INITIAL_FORMS&quot; value=&quot;0&quot; id=&quot;id_form-INITIAL_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-MIN_NUM_FORMS&quot; value=&quot;0&quot; id=&quot;id_form-MIN_NUM_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-MAX_NUM_FORMS&quot; value=&quot;1000&quot; id=&quot;id_form-MAX_NUM_FORMS&quot;&gt;</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-0-name&quot;&gt;Name:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;input id=&quot;id_form-0-name&quot; type=&quot;text&quot; name=&quot;form-0-name&quot; maxlength=&quot;100&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-0-title&quot;&gt;Title:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;select name=&quot;form-0-title&quot; id=&quot;id_form-0-title&quot;&gt;</span>
<span class="go">&lt;option value=&quot;&quot; selected&gt;---------&lt;/option&gt;</span>
<span class="go">&lt;option value=&quot;MR&quot;&gt;Mr.&lt;/option&gt;</span>
<span class="go">&lt;option value=&quot;MRS&quot;&gt;Mrs.&lt;/option&gt;</span>
<span class="go">&lt;option value=&quot;MS&quot;&gt;Ms.&lt;/option&gt;</span>
<span class="go">&lt;/select&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-0-id&quot; id=&quot;id_form-0-id&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last"><a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelformset_factory" title="django.forms.models.modelformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelformset_factory()</span></code></a> 使用 <a class="reference internal" href="../../ref/forms/formsets.html#django.forms.formsets.formset_factory" title="django.forms.formsets.formset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">formset_factory()</span></code></a> 来生成表单集。这意味着模型formset是一个知道如何与指定模型交互的普通formset的扩展。</p>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">当使用多表继承（ <a class="reference internal" href="../db/models.html#multi-table-inheritance"><span class="std std-ref">multi-table inheritance</span></a> ），通过 formset factory 生成的表单将包含父链接字段（默认是 <code class="docutils literal notranslate"><span class="pre">2_ptr</span></code> ）而不是 <code class="docutils literal notranslate"><span class="pre">id</span></code> 字段。</p>
</div>
<div class="section" id="s-changing-the-queryset">
<span id="changing-the-queryset"></span><h3>更改查询集<a class="headerlink" href="#changing-the-queryset" title="永久链接至标题">¶</a></h3>
<p>默认情况下，当您创建一个模型ormset时，formset将使用一个包含模型中所有对象（例如 <code class="docutils literal notranslate"><span class="pre">Author.objects.all()</span></code> ）的查询集。你可以通过使用 <code class="docutils literal notranslate"><span class="pre">queryset</span></code> 参数来覆盖这一行为：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">name__startswith</span><span class="o">=</span><span class="s1">&#39;O&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>或者，您可以创建一个子类，然后在 <code class="docutils literal notranslate"><span class="pre">__init__</span></code> 中设置 <code class="docutils literal notranslate"><span class="pre">self.queryset</span></code> ：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">BaseModelFormSet</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>

<span class="k">class</span> <span class="nc">BaseAuthorFormSet</span><span class="p">(</span><span class="n">BaseModelFormSet</span><span class="p">):</span>
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">queryset</span> <span class="o">=</span> <span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">name__startswith</span><span class="o">=</span><span class="s1">&#39;O&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>然后，将你的 <code class="docutils literal notranslate"><span class="pre">BaseAuthorFormSet</span></code> 类传递给工厂函数：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">),</span> <span class="n">formset</span><span class="o">=</span><span class="n">BaseAuthorFormSet</span><span class="p">)</span>
</pre></div>
</div>
<p>如果您想返回一个不包含 <em>任何</em> 已存在模型实例的formset，您可以指定一个空的QuerySet：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">none</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="section" id="s-changing-the-form">
<span id="changing-the-form"></span><h3>更改表单<a class="headerlink" href="#changing-the-form" title="永久链接至标题">¶</a></h3>
<p>默认情况下，当您使用 <code class="docutils literal notranslate"><span class="pre">modelformset_factory</span></code> 时，程序会用 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelform_factory" title="django.forms.models.modelform_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelform_factory()</span></code></a> 创建一个模型表单。这通常在指定自定义模型表单时很有用。例如，您可以创建一个具有自定义验证的自定义模型表单：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">AuthorForm</span><span class="p">(</span><span class="n">forms</span><span class="o">.</span><span class="n">ModelForm</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">Author</span>
        <span class="n">fields</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">clean_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># custom validation for the name field</span>
        <span class="o">...</span>
</pre></div>
</div>
<p>然后，将您的模型表单传递给工厂函数：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">form</span><span class="o">=</span><span class="n">AuthorForm</span><span class="p">)</span>
</pre></div>
</div>
<p>并不是总需要自定义模型表单。 <code class="docutils literal notranslate"><span class="pre">modelformset_factory</span></code> 函数有几个参数传递给 <code class="docutils literal notranslate"><span class="pre">modelform_factory</span></code> ，如下所述。</p>
</div>
<div class="section" id="s-specifying-widgets-to-use-in-the-form-with-widgets">
<span id="specifying-widgets-to-use-in-the-form-with-widgets"></span><h3>在表单中使用 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 指定部件。<a class="headerlink" href="#specifying-widgets-to-use-in-the-form-with-widgets" title="永久链接至标题">¶</a></h3>
<p>使用 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 参数，您可以设置一个字典值来为 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 指定字段自定义部件。这与 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 内部 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 类中 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 字典的工作方式一样：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">),</span>
<span class="gp">... </span>    <span class="n">widgets</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">Textarea</span><span class="p">(</span><span class="n">attrs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;cols&#39;</span><span class="p">:</span> <span class="mi">80</span><span class="p">,</span> <span class="s1">&#39;rows&#39;</span><span class="p">:</span> <span class="mi">20</span><span class="p">})})</span>
</pre></div>
</div>
</div>
<div class="section" id="s-enabling-localization-for-fields-with-localized-fields">
<span id="enabling-localization-for-fields-with-localized-fields"></span><h3>使用 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 来启用字段本地化<a class="headerlink" href="#enabling-localization-for-fields-with-localized-fields" title="永久链接至标题">¶</a></h3>
<p>您可以使用 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 参数为表单中的字段启用本地化。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span>
<span class="gp">... </span>    <span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;birth_date&#39;</span><span class="p">),</span>
<span class="gp">... </span>    <span class="n">localized_fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;birth_date&#39;</span><span class="p">,))</span>
</pre></div>
</div>
<p>如果 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 设置为特殊值 <code class="docutils literal notranslate"><span class="pre">'__all__'</span></code> ，则所有字段都将被本地化。</p>
</div>
<div class="section" id="s-id2">
<span id="id2"></span><h3>提供初始值<a class="headerlink" href="#id2" title="永久链接至标题">¶</a></h3>
<p>与常规表单集(formset)一样，在实例化 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelformset_factory" title="django.forms.models.modelformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelformset_factory()</span></code></a> 返回的模型表单集类时，可以通过指定初始参数来指定表单集中表单的初始数据。然而，对于模型表单集，初始值只适用于额外的表单，不会附加到已存在的模型实例。如果  <code class="docutils literal notranslate"><span class="pre">initial</span></code> 的长度超过了额外表单的数量，多余的初始值会被忽略。如果带有初始值的额外表单没有通过用户去改变，它们不会被验证或保存。</p>
</div>
<div class="section" id="s-saving-objects-in-the-formset">
<span id="s-id3"></span><span id="saving-objects-in-the-formset"></span><span id="id3"></span><h3>在表单集中保存对象<a class="headerlink" href="#saving-objects-in-the-formset" title="永久链接至标题">¶</a></h3>
<p>和 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 一样，你可以将数据保存为模型对象。这是通过表单集的 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法来完成的：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Create a formset instance with POST data.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">)</span>

<span class="c1"># Assuming all is valid, save the data.</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">instances</span> <span class="o">=</span> <span class="n">formset</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法返回已经保存到数据库的实例。如果一个给定实例的数据没有在绑定数据中改变，那么实例不会被保存到数据库，也不会包含在返回值里（上述例子中的 <code class="docutils literal notranslate"><span class="pre">instances</span></code> ）。</p>
<p>当表单中缺少字段时（比如因为它们被排除），这些字段不会被 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法设置。在选择使用字段里（ <a class="reference internal" href="#selecting-the-fields-to-use">Selecting the fields to use</a> ），你可以找到有关此限制的更多信息，这也适用于的普通的 <code class="docutils literal notranslate"><span class="pre">ModelForms</span></code> 。</p>
<p>传递 <code class="docutils literal notranslate"><span class="pre">commit=False</span></code>，返回未保存的模型实例：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># don&#39;t save to the database</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">instances</span> <span class="o">=</span> <span class="n">formset</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">for</span> <span class="n">instance</span> <span class="ow">in</span> <span class="n">instances</span><span class="p">:</span>
<span class="o">...</span>     <span class="c1"># do something with instance</span>
<span class="o">...</span>     <span class="n">instance</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>这会你在保存它们到数据库之前，附加数据给实例。如果你的表单集包含 <code class="docutils literal notranslate"><span class="pre">ManyToManyField</span></code> ，你也将需要调用 <code class="docutils literal notranslate"><span class="pre">formset.save_m2m()</span></code> 来确保正确保存了多对多关系。</p>
<p>在调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 之后，你的模型表单集将会有三个包含表单集更改的新属性：</p>
<dl class="attribute">
<dt id="django.forms.models.BaseModelFormSet.changed_objects">
<code class="descclassname">models.BaseModelFormSet.</code><code class="descname">changed_objects</code><a class="headerlink" href="#django.forms.models.BaseModelFormSet.changed_objects" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<dl class="attribute">
<dt id="django.forms.models.BaseModelFormSet.deleted_objects">
<code class="descclassname">models.BaseModelFormSet.</code><code class="descname">deleted_objects</code><a class="headerlink" href="#django.forms.models.BaseModelFormSet.deleted_objects" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<dl class="attribute">
<dt id="django.forms.models.BaseModelFormSet.new_objects">
<code class="descclassname">models.BaseModelFormSet.</code><code class="descname">new_objects</code><a class="headerlink" href="#django.forms.models.BaseModelFormSet.new_objects" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

</div>
<div class="section" id="s-limiting-the-number-of-editable-objects">
<span id="s-model-formsets-max-num"></span><span id="limiting-the-number-of-editable-objects"></span><span id="model-formsets-max-num"></span><h3>限制可编辑对象的数量<a class="headerlink" href="#limiting-the-number-of-editable-objects" title="永久链接至标题">¶</a></h3>
<p>和普通表单集一样，你可以使用 <code class="docutils literal notranslate"><span class="pre">max_num</span></code> 和 <code class="docutils literal notranslate"><span class="pre">extra</span></code> 参数来 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelformset_factory" title="django.forms.models.modelformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelformset_factory()</span></code></a> 来让 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelformset_factory" title="django.forms.models.modelformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelformset_factory()</span></code></a> 限制显示的额外表单数量。</p>
<p><code class="docutils literal notranslate"><span class="pre">max_num</span></code> 不会阻止显示已有对象：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
<span class="go">&lt;QuerySet [&lt;Author: Charles Baudelaire&gt;, &lt;Author: Paul Verlaine&gt;, &lt;Author: Walt Whitman&gt;]&gt;</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,),</span> <span class="n">max_num</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">x</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">formset</span><span class="o">.</span><span class="n">get_queryset</span><span class="p">()]</span>
<span class="go">[&#39;Charles Baudelaire&#39;, &#39;Paul Verlaine&#39;, &#39;Walt Whitman&#39;]</span>
</pre></div>
</div>
<p>同样，<code class="docutils literal notranslate"><span class="pre">extra=0</span></code> 不会阻止新模型实例的创建，因为你可以使用 JavaScript 来添加额外的表单或发送额外的POST数据。表单集还没有为“仅编辑”视图提供阻止创建新实例的功能。</p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">max_num</span></code> 的值大于现有关联对象的数量，只要总表单数不超过 <code class="docutils literal notranslate"><span class="pre">max_num</span></code> ，就会在表格集中添加额外的空白表单：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,),</span> <span class="n">max_num</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="n">formset</span><span class="p">:</span>
<span class="gp">... </span>    <span class="nb">print</span><span class="p">(</span><span class="n">form</span><span class="o">.</span><span class="n">as_table</span><span class="p">())</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-0-name&quot;&gt;Name:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;input id=&quot;id_form-0-name&quot; type=&quot;text&quot; name=&quot;form-0-name&quot; value=&quot;Charles Baudelaire&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-0-id&quot; value=&quot;1&quot; id=&quot;id_form-0-id&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-1-name&quot;&gt;Name:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;input id=&quot;id_form-1-name&quot; type=&quot;text&quot; name=&quot;form-1-name&quot; value=&quot;Paul Verlaine&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-1-id&quot; value=&quot;3&quot; id=&quot;id_form-1-id&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-2-name&quot;&gt;Name:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;input id=&quot;id_form-2-name&quot; type=&quot;text&quot; name=&quot;form-2-name&quot; value=&quot;Walt Whitman&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-2-id&quot; value=&quot;2&quot; id=&quot;id_form-2-id&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
<span class="go">&lt;tr&gt;&lt;th&gt;&lt;label for=&quot;id_form-3-name&quot;&gt;Name:&lt;/label&gt;&lt;/th&gt;&lt;td&gt;&lt;input id=&quot;id_form-3-name&quot; type=&quot;text&quot; name=&quot;form-3-name&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-3-id&quot; id=&quot;id_form-3-id&quot;&gt;&lt;/td&gt;&lt;/tr&gt;</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">max_num</span></code> 的值 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值)，它限制最多显示(1000)张表单，其实这相当于没有限制。</p>
</div>
<div class="section" id="s-using-a-model-formset-in-a-view">
<span id="using-a-model-formset-in-a-view"></span><h3>在视图中使用模型表单集<a class="headerlink" href="#using-a-model-formset-in-a-view" title="永久链接至标题">¶</a></h3>
<p>模型表单集与表单集非常相似。假设我们想要一个表单集来编辑 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 模型实例：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">modelformset_factory</span>
<span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="kn">import</span> <span class="n">render</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>

<span class="k">def</span> <span class="nf">manage_authors</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s1">&#39;POST&#39;</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">FILES</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">formset</span><span class="o">.</span><span class="n">is_valid</span><span class="p">():</span>
            <span class="n">formset</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
            <span class="c1"># do something.</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;manage_authors.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;formset&#39;</span><span class="p">:</span> <span class="n">formset</span><span class="p">})</span>
</pre></div>
</div>
<p>像你看到的那样，模型表单集的视图逻辑与普通的表单集并没有太大的不同。唯一的不同是我们调用 <code class="docutils literal notranslate"><span class="pre">formset.save()</span></code> 来保存数据到数据库里。（这已在上面的 <a class="reference internal" href="#saving-objects-in-the-formset"><span class="std std-ref">在表单集中保存对象</span></a> 中描述。）</p>
</div>
<div class="section" id="s-overriding-clean-on-a-modelformset">
<span id="s-model-formsets-overriding-clean"></span><span id="overriding-clean-on-a-modelformset"></span><span id="model-formsets-overriding-clean"></span><h3>覆盖 <code class="docutils literal notranslate"><span class="pre">ModelFormSet</span></code> 上的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code><a class="headerlink" href="#overriding-clean-on-a-modelformset" title="永久链接至标题">¶</a></h3>
<p>就像 <code class="docutils literal notranslate"><span class="pre">ModelForms</span></code> 一样，默认情况下，<code class="docutils literal notranslate"><span class="pre">ModelFormSet</span></code> 的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法将验证表单集中没有任何项目违反模型的唯一约束（ <code class="docutils literal notranslate"><span class="pre">unique</span></code>, <code class="docutils literal notranslate"><span class="pre">unique_together</span></code> 或 <code class="docutils literal notranslate"><span class="pre">unique_for_date|month|year</span></code> ）。如果你想覆盖 <code class="docutils literal notranslate"><span class="pre">ModelFormSet</span></code> 上的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法并保持这个验证，那么你必须调用父类的 <code class="docutils literal notranslate"><span class="pre">clean</span></code> 方法：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">BaseModelFormSet</span>

<span class="k">class</span> <span class="nc">MyModelFormSet</span><span class="p">(</span><span class="n">BaseModelFormSet</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">clean</span><span class="p">()</span>
        <span class="c1"># example custom validation across forms in the formset</span>
        <span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">forms</span><span class="p">:</span>
            <span class="c1"># your custom formset validation</span>
            <span class="o">...</span>
</pre></div>
</div>
<p>还要注意的是，到达此步时，已经为每个表单创建了独立模型实例。在 <code class="docutils literal notranslate"><span class="pre">form.cleaned_data</span></code> 里修改值不足以影响已保存的值。如果你想在 <code class="docutils literal notranslate"><span class="pre">ModelFormSet.clean()</span></code> 中修改值，你必须修改 <code class="docutils literal notranslate"><span class="pre">form.instance</span></code> ：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">BaseModelFormSet</span>

<span class="k">class</span> <span class="nc">MyModelFormSet</span><span class="p">(</span><span class="n">BaseModelFormSet</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">clean</span><span class="p">()</span>

        <span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">forms</span><span class="p">:</span>
            <span class="n">name</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">cleaned_data</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
            <span class="n">form</span><span class="o">.</span><span class="n">cleaned_data</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">name</span>
            <span class="c1"># update the instance value.</span>
            <span class="n">form</span><span class="o">.</span><span class="n">instance</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
</pre></div>
</div>
</div>
<div class="section" id="s-using-a-custom-queryset">
<span id="using-a-custom-queryset"></span><h3>使用自定义查询结果集<a class="headerlink" href="#using-a-custom-queryset" title="永久链接至标题">¶</a></h3>
<p>如前所述，你可以覆盖模型表单集使用的默认查询集：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">modelformset_factory</span>
<span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="kn">import</span> <span class="n">render</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Author</span>

<span class="k">def</span> <span class="nf">manage_authors</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">AuthorFormSet</span> <span class="o">=</span> <span class="n">modelformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s2">&quot;POST&quot;</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span>
            <span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">FILES</span><span class="p">,</span>
            <span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">name__startswith</span><span class="o">=</span><span class="s1">&#39;O&#39;</span><span class="p">),</span>
        <span class="p">)</span>
        <span class="k">if</span> <span class="n">formset</span><span class="o">.</span><span class="n">is_valid</span><span class="p">():</span>
            <span class="n">formset</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
            <span class="c1"># Do something.</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">AuthorFormSet</span><span class="p">(</span><span class="n">queryset</span><span class="o">=</span><span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">name__startswith</span><span class="o">=</span><span class="s1">&#39;O&#39;</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;manage_authors.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;formset&#39;</span><span class="p">:</span> <span class="n">formset</span><span class="p">})</span>
</pre></div>
</div>
<p>注意我们在这个例子里的 <code class="docutils literal notranslate"><span class="pre">POST</span></code> and <code class="docutils literal notranslate"><span class="pre">GET</span></code> 情况下传递了 <code class="docutils literal notranslate"><span class="pre">queryset</span></code> 参数。</p>
</div>
<div class="section" id="s-using-the-formset-in-the-template">
<span id="using-the-formset-in-the-template"></span><h3>在模板中使用表单集<a class="headerlink" href="#using-the-formset-in-the-template" title="永久链接至标题">¶</a></h3>
<p>有三种办法在 Django 模板中渲染表单集。</p>
<p>首先，你可以让表单集完成大部分工作：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span>
    <span class="cp">{{</span> <span class="nv">formset</span> <span class="cp">}}</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>其次，你可以手工渲染表单集，但需要让表单自己处理：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span>
    <span class="cp">{{</span> <span class="nv">formset.management_form</span> <span class="cp">}}</span>
    <span class="cp">{%</span> <span class="k">for</span> <span class="nv">form</span> <span class="k">in</span> <span class="nv">formset</span> <span class="cp">%}</span>
        <span class="cp">{{</span> <span class="nv">form</span> <span class="cp">}}</span>
    <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>当你手工渲染表单时，确保渲染了如上所述的管理表单。请查看文档的“管理”部分 （<a class="reference internal" href="formsets.html#understanding-the-managementform"><span class="std std-ref">management form documentation</span></a> ）</p>
<p>第三，你可以手工渲染每个字段：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span>
    <span class="cp">{{</span> <span class="nv">formset.management_form</span> <span class="cp">}}</span>
    <span class="cp">{%</span> <span class="k">for</span> <span class="nv">form</span> <span class="k">in</span> <span class="nv">formset</span> <span class="cp">%}</span>
        <span class="cp">{%</span> <span class="k">for</span> <span class="nv">field</span> <span class="k">in</span> <span class="nv">form</span> <span class="cp">%}</span>
            <span class="cp">{{</span> <span class="nv">field.label_tag</span> <span class="cp">}}</span> <span class="cp">{{</span> <span class="nv">field</span> <span class="cp">}}</span>
        <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
    <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>如果你选择使用第三种办法，并且你不使用 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">for</span> <span class="pre">%}</span></code> 循环遍历字段，那么你需要渲染主键字段。比如，如果你要渲染  <code class="docutils literal notranslate"><span class="pre">name</span></code> 和 <code class="docutils literal notranslate"><span class="pre">age</span></code> 字段：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span>
    <span class="cp">{{</span> <span class="nv">formset.management_form</span> <span class="cp">}}</span>
    <span class="cp">{%</span> <span class="k">for</span> <span class="nv">form</span> <span class="k">in</span> <span class="nv">formset</span> <span class="cp">%}</span>
        <span class="cp">{{</span> <span class="nv">form.id</span> <span class="cp">}}</span>
        <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">form.name</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">form.age</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
        <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span>
    <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>注意我们需要显式地渲染 <code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">form.id</span> <span class="pre">}}</span></code> 。这将确保在 <code class="docutils literal notranslate"><span class="pre">POST</span></code> 情况下，模型表单集正确工作。（这个例子假设主键名是 <code class="docutils literal notranslate"><span class="pre">id</span></code> 。如果你已经显式定义了不是名为 <code class="docutils literal notranslate"><span class="pre">id</span></code> 的主键，那你需要确保它正确地渲染。）</p>
</div>
</div>
<div class="section" id="s-inline-formsets">
<span id="s-id4"></span><span id="inline-formsets"></span><span id="id4"></span><h2>内联表单集<a class="headerlink" href="#inline-formsets" title="永久链接至标题">¶</a></h2>
<dl class="class">
<dt id="django.forms.models.BaseInlineFormSet">
<em class="property">class </em><code class="descclassname">models.</code><code class="descname">BaseInlineFormSet</code><a class="headerlink" href="#django.forms.models.BaseInlineFormSet" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>内联表单集是在模型表单集上一个很小的抽象层。这些表单集通过外键简化了处理相关对象的情况。假设你有两个模型：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Author</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">author</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">)</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</pre></div>
</div>
<p>如果你想创建一个允许你编辑属于特定作者的书籍的表单集，你可以这样做：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">inlineformset_factory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">BookFormSet</span> <span class="o">=</span> <span class="n">inlineformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">Book</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">,))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">author</span> <span class="o">=</span> <span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Mike Royko&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">BookFormSet</span><span class="p">(</span><span class="n">instance</span><span class="o">=</span><span class="n">author</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">BookFormSet</span></code>'s <a class="reference internal" href="formsets.html#formset-prefix"><span class="std std-ref">prefix</span></a> is <code class="docutils literal notranslate"><span class="pre">'book_set'</span></code> (<code class="docutils literal notranslate"><span class="pre">&lt;model</span> <span class="pre">name&gt;_set</span></code> ). 如果 <code class="docutils literal notranslate"><span class="pre">Book</span></code> 的 指向 <code class="docutils literal notranslate"><span class="pre">Author</span></code> 的 <code class="docutils literal notranslate"><span class="pre">ForeignKey</span></code> 有一个 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.ForeignKey.related_name" title="django.db.models.ForeignKey.related_name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">related_name</span></code></a> ，则使用它。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last"><a class="reference internal" href="../../ref/forms/models.html#django.forms.models.inlineformset_factory" title="django.forms.models.inlineformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">inlineformset_factory()</span></code></a> 使用 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.modelformset_factory" title="django.forms.models.modelformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">modelformset_factory()</span></code></a> 并标记 <code class="docutils literal notranslate"><span class="pre">can_delete=True</span></code> 。</p>
</div>
<div class="admonition seealso">
<p class="first admonition-title">参见</p>
<p class="last">手动渲染 can_delete 和 can_order 。（ <a class="reference internal" href="formsets.html#manually-rendered-can-delete-and-can-order"><span class="std std-ref">Manually rendered can_delete and can_order</span></a> ）</p>
</div>
<div class="section" id="s-overriding-methods-on-an-inlineformset">
<span id="overriding-methods-on-an-inlineformset"></span><h3>覆盖 <code class="docutils literal notranslate"><span class="pre">InlineFormSet</span></code> 上的方法<a class="headerlink" href="#overriding-methods-on-an-inlineformset" title="永久链接至标题">¶</a></h3>
<p>当覆盖 <code class="docutils literal notranslate"><span class="pre">InlineFormSet</span></code> 上的方法时，你可以继承 <a class="reference internal" href="#django.forms.models.BaseInlineFormSet" title="django.forms.models.BaseInlineFormSet"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseInlineFormSet</span></code></a> 而不是 <a class="reference internal" href="#django.forms.models.BaseModelFormSet" title="django.forms.models.BaseModelFormSet"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseModelFormSet</span></code></a> 。</p>
<p>比如，如果你想覆盖 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">BaseInlineFormSet</span>

<span class="k">class</span> <span class="nc">CustomInlineFormSet</span><span class="p">(</span><span class="n">BaseInlineFormSet</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">clean</span><span class="p">()</span>
        <span class="c1"># example custom validation across forms in the formset</span>
        <span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">forms</span><span class="p">:</span>
            <span class="c1"># your custom formset validation</span>
            <span class="o">...</span>
</pre></div>
</div>
<p>也可以看 <a class="reference internal" href="#model-formsets-overriding-clean"><span class="std std-ref">覆盖 ModelFormSet 上的 clean()</span></a> 。</p>
<p>然后当你创建自定义的内联表单集时，要传递一个可选参数 <code class="docutils literal notranslate"><span class="pre">formset</span></code> ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.forms</span> <span class="kn">import</span> <span class="n">inlineformset_factory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">BookFormSet</span> <span class="o">=</span> <span class="n">inlineformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">Book</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">,),</span>
<span class="gp">... </span>    <span class="n">formset</span><span class="o">=</span><span class="n">CustomInlineFormSet</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">author</span> <span class="o">=</span> <span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Mike Royko&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">formset</span> <span class="o">=</span> <span class="n">BookFormSet</span><span class="p">(</span><span class="n">instance</span><span class="o">=</span><span class="n">author</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-more-than-one-foreign-key-to-the-same-model">
<span id="more-than-one-foreign-key-to-the-same-model"></span><h3>同一个模型有多个外键<a class="headerlink" href="#more-than-one-foreign-key-to-the-same-model" title="永久链接至标题">¶</a></h3>
<p>如果你的模型包含多个外键，你需要解决使用 <code class="docutils literal notranslate"><span class="pre">fk_name</span></code> 来解决歧义。比如下面的模型：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Friendship</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">from_friend</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span>
        <span class="n">Friend</span><span class="p">,</span>
        <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">,</span>
        <span class="n">related_name</span><span class="o">=</span><span class="s1">&#39;from_friends&#39;</span><span class="p">,</span>
    <span class="p">)</span>
    <span class="n">to_friend</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span>
        <span class="n">Friend</span><span class="p">,</span>
        <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">,</span>
        <span class="n">related_name</span><span class="o">=</span><span class="s1">&#39;friends&#39;</span><span class="p">,</span>
    <span class="p">)</span>
    <span class="n">length_in_months</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">IntegerField</span><span class="p">()</span>
</pre></div>
</div>
<p>为了解决这个问题，你可以将 <code class="docutils literal notranslate"><span class="pre">fk_name</span></code> 用于 <a class="reference internal" href="../../ref/forms/models.html#django.forms.models.inlineformset_factory" title="django.forms.models.inlineformset_factory"><code class="xref py py-func docutils literal notranslate"><span class="pre">inlineformset_factory()</span></code></a>: ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">FriendshipFormSet</span> <span class="o">=</span> <span class="n">inlineformset_factory</span><span class="p">(</span><span class="n">Friend</span><span class="p">,</span> <span class="n">Friendship</span><span class="p">,</span> <span class="n">fk_name</span><span class="o">=</span><span class="s1">&#39;from_friend&#39;</span><span class="p">,</span>
<span class="gp">... </span>    <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;to_friend&#39;</span><span class="p">,</span> <span class="s1">&#39;length_in_months&#39;</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="section" id="s-using-an-inline-formset-in-a-view">
<span id="using-an-inline-formset-in-a-view"></span><h3>在视图中使用内联表单集<a class="headerlink" href="#using-an-inline-formset-in-a-view" title="永久链接至标题">¶</a></h3>
<p>你可以提供一个视图来允许用户编辑模型的相关对象。这里是相关做法：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">manage_books</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">author_id</span><span class="p">):</span>
    <span class="n">author</span> <span class="o">=</span> <span class="n">Author</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">author_id</span><span class="p">)</span>
    <span class="n">BookInlineFormSet</span> <span class="o">=</span> <span class="n">inlineformset_factory</span><span class="p">(</span><span class="n">Author</span><span class="p">,</span> <span class="n">Book</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">,))</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s2">&quot;POST&quot;</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">BookInlineFormSet</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">POST</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">FILES</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="n">author</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">formset</span><span class="o">.</span><span class="n">is_valid</span><span class="p">():</span>
            <span class="n">formset</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
            <span class="c1"># Do something. Should generally end with a redirect. For example:</span>
            <span class="k">return</span> <span class="n">HttpResponseRedirect</span><span class="p">(</span><span class="n">author</span><span class="o">.</span><span class="n">get_absolute_url</span><span class="p">())</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">formset</span> <span class="o">=</span> <span class="n">BookInlineFormSet</span><span class="p">(</span><span class="n">instance</span><span class="o">=</span><span class="n">author</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;manage_books.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;formset&#39;</span><span class="p">:</span> <span class="n">formset</span><span class="p">})</span>
</pre></div>
</div>
<p>请注意我们如何将 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 传递给 <code class="docutils literal notranslate"><span class="pre">POST</span></code> 和 <code class="docutils literal notranslate"><span class="pre">GET</span></code> 的。</p>
</div>
<div class="section" id="s-specifying-widgets-to-use-in-the-inline-form">
<span id="specifying-widgets-to-use-in-the-inline-form"></span><h3>指定要在内联表单中使用的 widgets<a class="headerlink" href="#specifying-widgets-to-use-in-the-inline-form" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">inlineformset_factory</span></code> 使用 <code class="docutils literal notranslate"><span class="pre">modelformset_factory</span></code>，并传递大部分参数给  <code class="docutils literal notranslate"><span class="pre">modelformset_factory</span></code> 。这意味着你可以使用 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 参数，就像将它传递给 <code class="docutils literal notranslate"><span class="pre">modelformset_factory</span></code> 一样。请查看 <a class="reference internal" href="#specifying-widgets-to-use-in-the-form-with-widgets">Specifying widgets to use in the form with widgets</a> 。</p>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">从模型创建表单</a><ul>
<li><a class="reference internal" href="#modelform"><code class="docutils literal notranslate"><span class="pre">ModelForm</span></code></a><ul>
<li><a class="reference internal" href="#field-types">字段类型</a></li>
<li><a class="reference internal" href="#a-full-example">一个完整的例子</a></li>
<li><a class="reference internal" href="#validation-on-a-modelform">验证 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code></a><ul>
<li><a class="reference internal" href="#overriding-the-clean-method">覆盖clean()方法</a></li>
<li><a class="reference internal" href="#interaction-with-model-validation">与模型验证交互</a></li>
<li><a class="reference internal" href="#considerations-regarding-model-s-error-messages">有关模型的 <code class="docutils literal notranslate"><span class="pre">error_messages</span></code> 的注意事项</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-save-method"><code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法</a></li>
<li><a class="reference internal" href="#selecting-the-fields-to-use">选择要使用的字段</a></li>
<li><a class="reference internal" href="#overriding-the-default-fields">覆盖默认字段</a></li>
<li><a class="reference internal" href="#enabling-localization-of-fields">启用对字段的本地化</a></li>
<li><a class="reference internal" href="#form-inheritance">表单继承</a></li>
<li><a class="reference internal" href="#providing-initial-values">提供初始值</a></li>
<li><a class="reference internal" href="#modelform-factory-function">ModelForm的工厂函数</a></li>
</ul>
</li>
<li><a class="reference internal" href="#model-formsets">模型表单集</a><ul>
<li><a class="reference internal" href="#changing-the-queryset">更改查询集</a></li>
<li><a class="reference internal" href="#changing-the-form">更改表单</a></li>
<li><a class="reference internal" href="#specifying-widgets-to-use-in-the-form-with-widgets">在表单中使用 <code class="docutils literal notranslate"><span class="pre">widgets</span></code> 指定部件。</a></li>
<li><a class="reference internal" href="#enabling-localization-for-fields-with-localized-fields">使用 <code class="docutils literal notranslate"><span class="pre">localized_fields</span></code> 来启用字段本地化</a></li>
<li><a class="reference internal" href="#id2">提供初始值</a></li>
<li><a class="reference internal" href="#saving-objects-in-the-formset">在表单集中保存对象</a></li>
<li><a class="reference internal" href="#limiting-the-number-of-editable-objects">限制可编辑对象的数量</a></li>
<li><a class="reference internal" href="#using-a-model-formset-in-a-view">在视图中使用模型表单集</a></li>
<li><a class="reference internal" href="#overriding-clean-on-a-modelformset">覆盖 <code class="docutils literal notranslate"><span class="pre">ModelFormSet</span></code> 上的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code></a></li>
<li><a class="reference internal" href="#using-a-custom-queryset">使用自定义查询结果集</a></li>
<li><a class="reference internal" href="#using-the-formset-in-the-template">在模板中使用表单集</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inline-formsets">内联表单集</a><ul>
<li><a class="reference internal" href="#overriding-methods-on-an-inlineformset">覆盖 <code class="docutils literal notranslate"><span class="pre">InlineFormSet</span></code> 上的方法</a></li>
<li><a class="reference internal" href="#more-than-one-foreign-key-to-the-same-model">同一个模型有多个外键</a></li>
<li><a class="reference internal" href="#using-an-inline-formset-in-a-view">在视图中使用内联表单集</a></li>
<li><a class="reference internal" href="#specifying-widgets-to-use-in-the-inline-form">指定要在内联表单中使用的 widgets</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="formsets.html"
                        title="上一章">表单集</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="media.html"
                        title="下一章">表单资源（ <code class="docutils literal notranslate"><span class="pre">Media</span></code> 类）</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../../_sources/topics/forms/modelforms.txt"
            rel="nofollow">显示源代码</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>快速搜索</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="转向" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">12月 07, 2021</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="formsets.html" title="表单集">previous</a>
     |
    <a href="../index.html" title="使用 Django" accesskey="U">up</a>
   |
    <a href="media.html" title="表单资源（ &lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;Media&lt;/span&gt;&lt;/code&gt; 类）">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>